/******************** (C) COPYRIGHT 2018 merafour ********************
* Author             : 冷月追风@merafour.blog.163.com
* Version            : V1.0.0
* Date               : 11/1/2019
* Description        : 数据存储接口.
********************************************************************************
* merafour.blog.163.com
* merafour@163.com
* github.com/Merafour
*******************************************************************************/
#include "cjsonstorage.h"
#include <stdio.h>
#include <QDebug>

uint32_t cJSONstorage::obj_count=0;

cJSONstorage::cJSONstorage(const char* _objName)
{
    memset(objName, 0, sizeof(objName));
    mutex.lock();
    obj_count++;
    memcpy(objName, "cj_1_", 5);
    objName[3] = static_cast<char>('0'+ obj_count);
    mutex.unlock();
    if(strlen(_objName)>sizeof (objName))
    {
        memcpy(&objName[5], "storage", strlen("storage"));
    }
    else
    {
        memcpy(&objName[5], _objName, strlen(_objName));
    }
    json_root = nullptr;
    json_root = cJSON_CreateObject();
    //debug();
    json_item = nullptr;
}

char *cJSONstorage::open(const char *path)
{
    size_t _size=0;
    size_t r_size=0;
    char* imagebyte=nullptr;

    FILE *fp = nullptr;
    qDebug() << "open cJSON file" ;
    fp = fopen(path, "rb");
    if(nullptr == fp)
    {
        qDebug() << "Unable to open" << QString::fromLocal8Bit(path);
        create_cutover(path);  // 文件不存在则创建
        goto bad;
    }
    fseek(fp, 0, SEEK_END);
    _size = static_cast<size_t>(ftell(fp));
    if(0!=fseek(fp, 0, SEEK_SET))
    {
        qDebug() << "Unable to SET" << QString::fromLocal8Bit(path);
        goto bad;
    }
    qDebug() << "_size:" << _size;
    r_size = _size - _size%1024+2048;
    //if(nullptr == imagebyte) imagebyte = (char*)malloc(r_size);
    if(nullptr == imagebyte) imagebyte = reinterpret_cast<char *>(malloc(r_size));
    if(nullptr == imagebyte)
    {
        qDebug() << "malloc space fail!";
        goto bad;
    }
    memset(imagebyte, 0x00, r_size);
    r_size = fread(imagebyte, 1, _size, fp);
    qDebug() << "r_size:" << r_size;
    if(_size != r_size)
    {
        qDebug() << "read music fail" ;
        goto bad;
    }
    fclose(fp);
    //qDebug("imagebyte: %s", imagebyte);
    return imagebyte;
bad:
    if(nullptr != fp) fclose(fp);
    return nullptr;
}

cJSON* cJSONstorage::opencJSON(const char *path)
{
    cJSON* _root;
    char* imagebyte=nullptr;
    char* json_str=nullptr;
    //qDebug() << "opencJSON" ;
    qDebug("opencJSON: %s", path);
    imagebyte = open(path);
    //qDebug() << "opencJSON ...1" ;
    if(nullptr==imagebyte)
    {
        imagebyte=open(path);
    }
    if(nullptr==imagebyte)
    {
        qDebug() << "转换文件无法打开" ;
        return nullptr;
    }
//    qDebug() << "opencJSON ...2" ;
//    qDebug("imagebyte: %08X, %08X", imagebyte, imagebyte[0]);
//    qDebug("imagebyte: %s", imagebyte);
    //qDebug() << "opencJSON ...3" ;
    _root = cJSON_Parse(imagebyte);
    //qDebug() << "opencJSON ...4" ;
    if(nullptr == _root)
    {
        qDebug("Parse JSON fail");
        goto bad;
    }
    //qDebug() << "opencJSON ...5" ;
    json_str = cJSON_Print(_root);
    //qDebug() << "opencJSON ...6" ;
    //json_str = cJSON_PrintUnformatted(root);
    //QiTranslator::savecJSON(path, json_str);
    qDebug("json: %s", json_str);
    //fflush(stdout);
    if(nullptr!=json_str) free(json_str);
    if(nullptr != imagebyte) free(imagebyte);
    return _root;
bad:
    //qDebug() << "opencJSON ...7" ;
    if(nullptr!=json_str) free(json_str);
    //qDebug() << "opencJSON ...8" ;
    if(nullptr != imagebyte) free(imagebyte);
    //qDebug() << "opencJSON ...9" ;
    return nullptr;
}

int cJSONstorage::opencJSON(const char *path, cJSON* *root)
{
    cJSON* _root;
    mutex.lock();
    //json_root = cJSON_CreateObject();
    //if(nullptr!=json_root) free(json_root);
    _root = opencJSON(path);
    //ret = opencJSON("Language1.txt", json_root);
    mutex.unlock();
    //qDebug("Parse JSON fail .. 3");
    if(nullptr!=_root)
    {
        *root = _root;
        return 0;
    }
    //qDebug("Parse JSON fail .. 2");
    return -1;
}

int cJSONstorage::savecJSON(const char *path, const char *json_str)
{
    size_t _size=0;
    size_t w_size=0;
    FILE* fp = nullptr;

    fp = fopen(path, "w+");
    if(nullptr == fp)
    {
        qDebug() << "Unable to open" << QString::fromLocal8Bit(path);
        goto bad;
    }
    if(0!=fseek(fp, 0, SEEK_SET))
    {
        qDebug() << "Unable to SET" << QString::fromLocal8Bit(path);
        goto bad;
    }
    _size = strlen(json_str);
    //qDebug() << "json size:" << _size;
    w_size = fwrite(json_str, 1, _size, fp);
    //qDebug() << "w_size:" << w_size;
    if(_size != w_size)
    {
        qDebug() << "write cJSON fail" ;
        goto bad;
    }
    fclose(fp);
    return 0;

bad:
    if(nullptr != fp) fclose(fp);
    return -1;
}

int cJSONstorage::savecJSON(const char *path, const cJSON* root)
{
    size_t _size=0;
    size_t w_size=0;
    FILE* fp = nullptr;
    char* json_str;
    static const char format[]=",\n\"item\":";

    //json_str = cJSON_Print(root);
    json_str = cJSON_PrintUnformatted(root);

    //fp = fopen(path, "w+");
    fp = fopen(path, "at+");
    if(nullptr == fp)
    {
        //qDebug() << "Unable to open" << QString::fromLocal8Bit(path);
        goto bad;
    }
    if(0!=fseek(fp, 0, SEEK_SET))
    {
        //qDebug() << "Unable to SET" << QString::fromLocal8Bit(path);
        goto bad;
    }
    _size = strlen(format);
    w_size = fwrite(format, 1, _size, fp);
    if(_size != w_size)
    {
        //qDebug() << "write cJSON fail" ;
        goto bad;
    }
    _size = strlen(json_str);
    //qDebug() << "json size:" << _size;
    w_size = fwrite(json_str, 1, _size, fp);
    //qDebug() << "w_size:" << w_size;
    if(_size != w_size)
    {
        //qDebug() << "write cJSON fail" ;
        goto bad;
    }
    fclose(fp);
    if(nullptr != json_str) free(json_str);
    return 0;

bad:
    if(nullptr != fp) fclose(fp);
    if(nullptr != json_str) free(json_str);
    return -1;
}

int cJSONstorage::create_cutover(const char *path)
{
    //uint16_t i;
    cJSON* root =  cJSON_CreateObject();
    //cJSON* objroot =  cJSON_CreateObject();
    char* json_str;

    cJSON_AddItemToObject(root, "file", cJSON_CreateString(path));
    cJSON_AddItemToObject(root, "create", cJSON_CreateString(QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss").toLocal8Bit().data()));

    json_str = cJSON_Print(root);
    //json_str = cJSON_PrintUnformatted(root);
    savecJSON(path, json_str);

//bad:
    cJSON_Delete(root);
    //free(root);
    free(json_str);
    return 0;
}
